﻿
using Furion.DatabaseAccessor;
using Furion.DataEncryption;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.Core;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using Furion.DatabaseAccessor.Extensions;
using Furion.DistributedIDGenerator;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading.Tasks;
using Furion.Core.Entities.Enums;
using Furion.RemoteRequest.Extensions;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Caching.Memory;


namespace Furion.Application.Weixin
{
    /// <summary>
    /// 微信接口
    /// </summary>
    [AppAuthorize, ApiDescriptionSettings("System", Name = "Weixin", Order = 1, Tag = "微信接口")]
    public class WeixinService : IDynamicApiController
    {

        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IRepository<User> _userRepository;
        private readonly IMemoryCache _memoryCache;

        public WeixinService(IHttpContextAccessor httpContextAccessor, IRepository<User> userRepository, IMemoryCache memoryCache)
        {
            _httpContextAccessor = httpContextAccessor;
            _userRepository = userRepository;
            _memoryCache = memoryCache;
        }



        /// <summary>
        /// AccessToken
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous, HttpGet("/WeiXin/GetAccessToken")]
        public async Task<WxOpenAccessToken> GetWxOpenAccessToken()
        {
            var token = _memoryCache.Get<WxOpenAccessToken>(ClaimConst.WeixinAccessToken);
            if (token == null)
            {
                string WxOpenAccessTokenHost = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
                string WxOpenAppID = App.Configuration["AppInfo:WxOpenAppID"];
                string WxOpenAppSecret = App.Configuration["AppInfo:WxOpenAppSecret"];
                string HostUrl = string.Format(WxOpenAccessTokenHost, WxOpenAppID, WxOpenAppSecret);

                token = await HostUrl.GetAsAsync<WxOpenAccessToken>();
                _memoryCache.Set(ClaimConst.WeixinAccessToken, token, DateTime.Now.AddSeconds(7200));
            }
            return token;
        }

        /// <summary>
        /// 获取用户OpenID
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        [AllowAnonymous, HttpGet("/WeiXin/GetOpenId")]
        public async Task<WxCode2Session> Code2Session(string code)
        {
            string WxOpenAppID = App.Configuration["AppInfo:WxOpenAppID"];
            string WxOpenAppSecret = App.Configuration["AppInfo:WxOpenAppSecret"];
            string Code2SessionHost = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
            string HostUrl = string.Format(Code2SessionHost, WxOpenAppID, WxOpenAppSecret, code);
            var item = await HostUrl.GetAsAsync<WxCode2Session>();

            return item;
        }


        /// <summary>
        /// 客服消息:发送文本
        /// </summary>
        /// <param name="para"></param>
        /// <returns></returns>
        [AllowAnonymous, HttpPost("/WeiXin/MessageSend")]
        public async Task<MessageSendOutPut> MessageSend(MessageSendPara para)
        {
            var token = _memoryCache.Get<WxOpenAccessToken>(ClaimConst.WeixinAccessToken);
            if (token == null)
            {
                string WxOpenAccessTokenHost = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
                string WxOpenAppID = App.Configuration["AppInfo:WxOpenAppID"];
                string WxOpenAppSecret = App.Configuration["AppInfo:WxOpenAppSecret"];
                string HostUrl = string.Format(WxOpenAccessTokenHost, WxOpenAppID, WxOpenAppSecret);

                token = await HostUrl.GetAsAsync<WxOpenAccessToken>();
                _memoryCache.Set(ClaimConst.WeixinAccessToken, token, DateTime.Now.AddSeconds(7200));
            }

            string Url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + token.access_token;

            var text = new { content = para.Content };

            var data = new { touser = para.openid, text = text };
            var val = await Url.SetBody(data, "application/json").PostAsAsync<MessageSendOutPut>();

            return val;
        }


        /// <summary>
        /// 客服消息:发送小程序
        /// </summary>
        /// <param name="para"></param>
        /// <returns></returns>
        [AllowAnonymous, HttpPost("/WeiXin/MessageSendWxApp")]
        public async Task<MessageSendOutPut> MessageSendWxApp(MessageSendWxAppPara para)
        {
            var token = _memoryCache.Get<WxOpenAccessToken>(ClaimConst.WeixinAccessToken);
            if (token == null)
            {
                string WxOpenAccessTokenHost = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
                string WxOpenAppID = App.Configuration["AppInfo:WxOpenAppID"];
                string WxOpenAppSecret = App.Configuration["AppInfo:WxOpenAppSecret"];
                string HostUrl = string.Format(WxOpenAccessTokenHost, WxOpenAppID, WxOpenAppSecret);

                token = await HostUrl.GetAsAsync<WxOpenAccessToken>();
                _memoryCache.Set(ClaimConst.WeixinAccessToken, token, DateTime.Now.AddSeconds(7200));
            }

            string Url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + token.access_token;

            var miniprogrampage = new { title = para.title, pagepath = para.pagepath, thumb_media_id = "H1W0SuBq1zmFiGpa_bpf9QrvSIfhbqqAA92PlAnfPLWuQp2s8oTEJhOkoj2AdlKv" };

            var data = new { touser = para.openid, msgtype = "miniprogrampage", miniprogrampage = miniprogrampage };
            var val = await Url.SetBody(data, "application/json").PostAsAsync<MessageSendOutPut>();

            return val;
        }


        /// <summary>
        /// 发送订阅消息：单发
        /// </summary>
        /// <param name="para"></param>
        /// <returns></returns>
        [AllowAnonymous, HttpPost("/WeiXin/Subscribe")]
        public async Task<List<MessageSendResult>> Subscribe(SubscribePara para)
        {
            var userInfo = await _userRepository.FirstOrDefaultAsync(a => para.UserId == a.Id);
            if (userInfo != null)
            {
                var results = new List<MessageSendResult>();
                var token = _memoryCache.Get<WxOpenAccessToken>(ClaimConst.WeixinAccessToken);
                if (token == null)
                {
                    string WxOpenAccessTokenHost = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
                    string WxOpenAppID = App.Configuration["AppInfo:WxOpenAppID"];
                    string WxOpenAppSecret = App.Configuration["AppInfo:WxOpenAppSecret"];
                    string HostUrl = string.Format(WxOpenAccessTokenHost, WxOpenAppID, WxOpenAppSecret);

                    token = await HostUrl.GetAsAsync<WxOpenAccessToken>();
                    _memoryCache.Set(ClaimConst.WeixinAccessToken, token, DateTime.Now.AddSeconds(7200));
                }
                string Url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + token.access_token;

                if (!string.IsNullOrEmpty(userInfo.OpenId))
                {
                    /*
                        审核结果{{phrase1.DATA}} 5个以内汉字
                        审核内容{{thing2.DATA}}  20个以内字符	
                        审核时间{{date3.DATA}}   2019年10月1日 15:01
                        备注{{thing7.DATA}}      20个以内字符	
                        */

                    string TemplateID = App.Configuration["AppInfo:TemplateID"];

                    string post_body = "{";
                    post_body += "\"touser\": \"" + userInfo.OpenId + "\",";
                    post_body += "\"template_id\": \"" + TemplateID + "\",";  //YoSEspP6Dr05QCw4Mc9N2r43bmGZ342Uil4dI-ztBwM
                    post_body += "\"page\": \"" + para.page + "\",";
                    post_body += "\"data\": {";
                    post_body += "\"phrase1\": {\"value\": \"" + para.auth_result + "\"},";
                    post_body += "\"thing2\": {\"value\": \"" + para.auth_content + "\"},";
                    post_body += "\"date3\": {\"value\": \"" + DateTime.Now.ToString("yyyy年MM月dd日 HH:mm") + "\"},";
                    post_body += "\"thing7\": {\"value\": \"" + para.auth_remark + "\"}";
                    post_body += "}}";
                    var val = await Url.SetBody(post_body, "application/json").PostAsAsync<MessageSendOutPut>();

                    if (val.errcode == 0)
                    {
                        results.Add(new MessageSendResult { Msg = val.errmsg, NickName = userInfo.NickName, UserId = userInfo.Id });
                    }
                    else
                    {
                        results.Add(new MessageSendResult { Msg = val.errmsg + "，没有订阅消息", NickName = userInfo.NickName, UserId = userInfo.Id });
                    }
                }
                else
                {
                    results.Add(new MessageSendResult { Msg = "帐号没有绑定微信", NickName = userInfo.NickName, UserId = userInfo.Id });
                }
                return results;
            }
            else
            {
                throw Oops.Oh("用户不存在");
            }
        }

        /// <summary>
        /// 发送订阅消息：群发
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AllowAnonymous, HttpPost("/WeiXin/SubscribeRange")]
        public async Task<List<MessageSendResult>> SubscribeRange(SubscribeRangePara input)
        {
            if (input.paras.Count > 0)
            {
                var results = new List<MessageSendResult>();
                var token = _memoryCache.Get<WxOpenAccessToken>(ClaimConst.WeixinAccessToken);
                if (token == null)
                {
                    string WxOpenAccessTokenHost = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
                    string WxOpenAppID = App.Configuration["AppInfo:WxOpenAppID"];
                    string WxOpenAppSecret = App.Configuration["AppInfo:WxOpenAppSecret"];
                    string HostUrl = string.Format(WxOpenAccessTokenHost, WxOpenAppID, WxOpenAppSecret);

                    token = await HostUrl.GetAsAsync<WxOpenAccessToken>();
                    _memoryCache.Set(ClaimConst.WeixinAccessToken, token, DateTime.Now.AddSeconds(7200));
                }
                string Url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + token.access_token;

                foreach (var item in input.paras)
                {
                    var userInfo = await _userRepository.FirstOrDefaultAsync(a => item.UserId == a.Id);
                    if (userInfo != null)
                    {
                        if (!string.IsNullOrEmpty(userInfo.OpenId))
                        {
                            string TemplateID = App.Configuration["AppInfo:TemplateID"];

                            string post_body = "{";
                            post_body += "\"touser\": \"" + userInfo.OpenId + "\",";
                            post_body += "\"template_id\": \"" + TemplateID + "\",";
                            post_body += "\"page\": \"" + item.page + "\",";
                            post_body += "\"data\": {";
                            post_body += "\"phrase1\": {\"value\": \"" + item.auth_result + "\"},";
                            post_body += "\"thing2\": {\"value\": \"" + item.auth_content + "\"},";
                            post_body += "\"date3\": {\"value\": \"" + DateTime.Now.ToString("yyyy年MM月dd日 HH:mm") + "\"},";
                            post_body += "\"thing7\": {\"value\": \"" + item.auth_remark + "\"}";
                            post_body += "}}";
                            var val = await Url.SetBody(post_body, "application/json").PostAsAsync<MessageSendOutPut>();

                            if (val.errcode == 0)
                            {
                                results.Add(new MessageSendResult { Msg = val.errmsg, NickName = userInfo.NickName, UserId = userInfo.Id });
                            }
                            else
                            {
                                results.Add(new MessageSendResult { Msg = val.errmsg + "，没有订阅消息", NickName = userInfo.NickName, UserId = userInfo.Id });
                            }
                        }
                        else
                        {
                            results.Add(new MessageSendResult { Msg = "帐号没有绑定微信", NickName = userInfo.NickName, UserId = userInfo.Id });
                        }
                    }
                    else
                    {
                        results.Add(new MessageSendResult { Msg = "用户不存在", NickName = "", UserId = item.UserId });
                    }
                }
                return results;
            }
            else
            {
                throw Oops.Oh("参数错误");
            }
        }

    }
}
